package com.weifly.weistock.module.stockmonitor;

import com.weifly.weistock.core.chart.bo.ChartDataSetBO;
import com.weifly.weistock.core.chart.bo.ChartSerieBO;
import com.weifly.weistock.core.market.bo.StockDayBO;
import com.weifly.weistock.core.monitor.bo.MonitorStatusBO;
import com.weifly.weistock.core.util.ConvertUtils;
import com.weifly.weistock.module.stockdata.bo.GetDayListRequest;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorConfigBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorDayBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorHoldBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorStatusBO;
import org.apache.commons.lang3.StringUtils;

import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.weifly.weistock.core.constant.WeistockConstants.PAGE_LIMIT;

/**
 * converter
 *
 * @author weifly
 * Create at 2021/7/2
 */
public class StockMonitorConverter {

    public static Map<String, Object> convertToStockMonitorDTO(StockMonitorHoldBO stockMonitorHoldBO) {
        StockMonitorConfigBO stockMonitorConfigBO = stockMonitorHoldBO.getStockMonitorConfig();
        Map<String, Object> info = new HashMap<>();
        info.put("stockCode", stockMonitorConfigBO.getStockCode());
        info.put("stockName", StringUtils.isBlank(stockMonitorConfigBO.getStockName()) ? "" : stockMonitorConfigBO.getStockName());
        List<StockMonitorDayBO> dayList = stockMonitorConfigBO.getDayList();
        if (dayList.size() > 0) {
            StockMonitorDayBO endDay = dayList.get(dayList.size() - 1);
            info.put("endDay", endDay.getDay());
            info.put("upRate", endDay.getUp_rate());
            info.put("upRateAllPercent", endDay.getUp_rate_all_percent());
            info.put("downRate", endDay.getDown_rate());
            info.put("downRateAllPercent", endDay.getDown_rate_all_percent());
            info.put("diffRatePercent", endDay.getDiff_rate_percent());
        }
        return info;
    }

    /**
     * 获得指定天集合
     */
    public static Map<String, Object> getDayList(StockMonitorHoldBO stockMonitorHoldBO, GetDayListRequest request) {
        // 获得天集合
        List<StockMonitorDayBO> dayList = new ArrayList<>();
        if (stockMonitorHoldBO != null && stockMonitorHoldBO.getStockMonitorConfig() != null) {
            StockMonitorConfigBO stockMonitorConfigBO = stockMonitorHoldBO.getStockMonitorConfig();
            int totalDayCount = stockMonitorConfigBO.getDayList().size();
            // 降序遍历
            for (int i = totalDayCount - 1; i >= 0; i--) {
                StockMonitorDayBO dayBO = stockMonitorConfigBO.getDayList().get(i);
                if (!filterMonitorDay(dayBO, request)) {
                    dayList.add(dayBO);
                    if (dayList.size() >= request.getLimit()) {
                        break;
                    }
                }
            }
        }
        // 组装返回内容
        boolean haveMore = false;
        if (dayList.size() > request.getLimit() - 1) {
            haveMore = true;
            dayList = dayList.subList(0, request.getLimit() - 1); // 返回 limit-1 条记录
        }
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("haveMore", haveMore);
        dataMap.put("recordList", ConvertUtils.convert(dayList, StockMonitorConverter::convertToStockMonitorDayDTO));
        return dataMap;
    }

    /**
     * 需要过滤的记录，则返回true
     */
    private static boolean filterMonitorDay(StockMonitorDayBO dayBO, GetDayListRequest request) {
        if (StringUtils.isNotBlank(request.getDate())) {
            int dataCompare = dayBO.getDay().compareTo(request.getDate());
            if (dataCompare >= 0) {
                // record date 大或相等，需要过滤
                return true;
            }
        }
        return false;
    }

    public static Map<String, Object> convertToStockMonitorDayDTO(StockMonitorDayBO stockMonitorDay) {
        Map<String, Object> info = new HashMap<>();
        info.put("day", stockMonitorDay.getDay());
        info.put("close", stockMonitorDay.getClose());
        info.put("diff", stockMonitorDay.getDiff());
        info.put("rate", stockMonitorDay.getRate());
        if (StringUtils.isNotBlank(stockMonitorDay.getUp_lowest_day())) {
            info.put("upLowestDay", stockMonitorDay.getUp_lowest_day());
            info.put("upLowestPrice", stockMonitorDay.getUp_lowest_price());
            info.put("upDiff", stockMonitorDay.getUp_diff());
            info.put("upRate", stockMonitorDay.getUp_rate());
            info.put("upRateAllPercent", stockMonitorDay.getUp_rate_all_percent());
            info.put("diffRatePercent", stockMonitorDay.getDiff_rate_percent());
        }
        if (StringUtils.isNotBlank(stockMonitorDay.getDown_highest_day())) {
            info.put("downHighestDay", stockMonitorDay.getDown_highest_day());
            info.put("downHighestPrice", stockMonitorDay.getDown_highest_price());
            info.put("downDiff", stockMonitorDay.getDown_diff());
            info.put("downRate", stockMonitorDay.getDown_rate());
            info.put("downRateAllPercent", stockMonitorDay.getDown_rate_all_percent());
        }
        return info;
    }

    /**
     * 用股票数据填充DataSet
     */
    public static void fillDataSetByStockData(ChartDataSetBO dataSet, List<StockDayBO> dayList, String serieName) {
        if (dayList.isEmpty()) {
            return;
        }

        ChartSerieBO chartSerie = new ChartSerieBO();
        chartSerie.setName(serieName);
        chartSerie.setType("line");
        DecimalFormat decimalFormat = new DecimalFormat("0.####");
        for (StockDayBO dayBO : dayList) {
            dataSet.getPointList().add(dayBO.getDay());
            chartSerie.getDataList().add(Double.valueOf(decimalFormat.format(dayBO.getClose())));
        }
        dataSet.getSerieList().add(chartSerie);
    }

    /**
     * 加载天列表，用于chart显示
     *
     * @param stockMonitorHoldBO 股票监控hold信息
     * @param lowDay             日期下限
     * @return lowDay到最新日期之间的所有记录
     */
    public static List<StockMonitorDayBO> loadStockMonitorDayList(StockMonitorHoldBO stockMonitorHoldBO, String lowDay) {
        LinkedList<StockMonitorDayBO> dayList = new LinkedList<>();
        if (StringUtils.isBlank(lowDay)) {
            return dayList;
        }
        if (stockMonitorHoldBO == null || stockMonitorHoldBO.getStockMonitorConfig() == null) {
            return dayList;
        }
        StockMonitorConfigBO stockMonitorConfigBO = stockMonitorHoldBO.getStockMonitorConfig();

        ListIterator<StockMonitorDayBO> dayIter = stockMonitorConfigBO.getDayList().listIterator(stockMonitorConfigBO.getDayList().size());
        while (dayIter.hasPrevious()) {
            StockMonitorDayBO dayBO = dayIter.previous();
            if (lowDay.compareTo(dayBO.getDay()) > 0) {
                break;
            } else {
                dayList.addFirst(dayBO);
            }
        }
        return dayList;
    }

    /**
     * 用股票监控数据填充DataSet
     */
    public static void fillDataSetByStockMonitorDayList(ChartDataSetBO dataSet, List<StockMonitorDayBO> stockMonitorDayList) {
        if (dataSet.getPointList().isEmpty()) {
            return; // 无坐标数据
        }
        // 最小值集合
        ChartSerieBO lowestSerie = new ChartSerieBO();
        lowestSerie.setName("最小值");
        lowestSerie.setType("line");
        dataSet.getSerieList().add(lowestSerie);
        // 上涨百分比
        ChartSerieBO upPercentSerie = new ChartSerieBO();
        upPercentSerie.setName("上涨百分比");
        upPercentSerie.setType("line");
        dataSet.getSerieList().add(upPercentSerie);
        // 最大值集合
        ChartSerieBO highestSerie = new ChartSerieBO();
        highestSerie.setName("最大值");
        highestSerie.setType("line");
        dataSet.getSerieList().add(highestSerie);
        // 下跌百分比
        ChartSerieBO downPercentSerie = new ChartSerieBO();
        downPercentSerie.setName("下跌百分比");
        downPercentSerie.setType("line");
        dataSet.getSerieList().add(downPercentSerie);
        // 百分比差值
        ChartSerieBO diffRatePercentSerie = new ChartSerieBO();
        diffRatePercentSerie.setName("百分比差值");
        diffRatePercentSerie.setType("line");
        dataSet.getSerieList().add(diffRatePercentSerie);
        Map<String, StockMonitorDayBO> stockMonitorDayMap = stockMonitorDayList.stream().collect(Collectors.toMap(StockMonitorDayBO::getDay, Function.identity()));
        for (String point : dataSet.getPointList()) {
            StockMonitorDayBO stockMonitorDayBO = stockMonitorDayMap.get(point);
            lowestSerie.getDataList().add(stockMonitorDayBO == null ? 0 : stockMonitorDayBO.getUp_lowest_price());
            upPercentSerie.getDataList().add(stockMonitorDayBO == null ? 0 : stockMonitorDayBO.getUp_rate_all_percent());
            highestSerie.getDataList().add(stockMonitorDayBO == null ? 0 : stockMonitorDayBO.getDown_highest_price());
            downPercentSerie.getDataList().add(stockMonitorDayBO == null ? 0 : stockMonitorDayBO.getDown_rate_all_percent());
            diffRatePercentSerie.getDataList().add(stockMonitorDayBO == null ? 0 : stockMonitorDayBO.getDiff_rate_percent());
        }
    }

    /**
     * 生成监控信息
     */
    public static Map<String, Object> convertToMonitorStatus(MonitorStatusBO statusBO, List<StockMonitorHoldBO> stockList) {
        Map<String, Object> statusMap = new HashMap<>();
        statusMap.put("status", statusBO.getStatus());
        statusMap.put("date", statusBO.getDate());
        statusMap.put("time", statusBO.getTime());
        List<Map<String, Object>> stockMapList = new ArrayList<>();
        for (StockMonitorHoldBO holdBO : stockList) {
            Map<String, Object> stockMap = new HashMap<>();
            stockMap.put("stockCode", holdBO.getStockMonitorConfig().getStockCode());
            stockMap.put("stockName", holdBO.getStockMonitorConfig().getStockName());
            StockMonitorStatusBO stockMonitorStatusBO = holdBO.getStockMonitorStatus();
            if (stockMonitorStatusBO != null) {
                stockMap.put("nowPrice", stockMonitorStatusBO.getNowPrice());
                stockMap.put("nowRate", stockMonitorStatusBO.getNowRate());
                stockMap.put("priceDate", stockMonitorStatusBO.getPriceDate());
                stockMap.put("priceTime", stockMonitorStatusBO.getPriceTime());
                stockMap.put("upRate", stockMonitorStatusBO.getUp_rate());
                stockMap.put("upRateAllPercent", stockMonitorStatusBO.getUp_rate_all_percent());
                stockMap.put("downRate", stockMonitorStatusBO.getDown_rate());
                stockMap.put("downRateAllPercent", stockMonitorStatusBO.getDown_rate_all_percent());
                stockMap.put("diffRatePercent", stockMonitorStatusBO.getDiff_rate_percent());
                if (StringUtils.isNotEmpty(stockMonitorStatusBO.getTradeStockCode())) {
                    stockMap.put("tradeStockCode", stockMonitorStatusBO.getTradeStockCode());
                }
                if (StringUtils.isNotEmpty(stockMonitorStatusBO.getTradeStockName())) {
                    stockMap.put("tradeStockName", stockMonitorStatusBO.getTradeStockName());
                }
                if (stockMonitorStatusBO.getTradeNowPrice() != null) {
                    stockMap.put("tradeNowPrice", stockMonitorStatusBO.getTradeNowPrice());
                }
                if (stockMonitorStatusBO.getTradeNowRate() != null) {
                    stockMap.put("tradeNowRate", stockMonitorStatusBO.getTradeNowRate());
                }
                if (stockMonitorStatusBO.getTradeLastPrice() != null) {
                    stockMap.put("tradeLastPrice", stockMonitorStatusBO.getTradeLastPrice());
                }
                if (stockMonitorStatusBO.getTradeLastRate() != null) {
                    stockMap.put("tradeLastRate", stockMonitorStatusBO.getTradeLastRate());
                }
            }
            stockMapList.add(stockMap);
        }
        statusMap.put("stockList", stockMapList);
        return statusMap;
    }
}
